<?php
/**
 * 缓存处理管理类
 * 
 * 缓存单元的数据结构
 * array(
 *     'time' => time(),    // 缓存写入时的时间戳
 *     'expire' => $expire, // 缓存过期时间
 *     'valid' => true,     // 缓存是否有效
 *     'data' => $value     // 缓存的值
 * );
 * 
 * ============================================================================
 * 版权所有: (c) 2009-2011，<UEShop Inc>，并保留所有权利。
 * 网站地址: http://www.ueshop.cn
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用；
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 * @author cmpan
 * @copyright   Copyright (c) 2009-2011 UEShop Inc. (http://www.ueshop.cn)
 * @license     http://www.ueshop.cn/1_0.txt
 */
final class UE_Cache {
	/**
	 * 缓存过期时间长度(s)
	 *
	 * @var int
	 */
	private $_expire = 3600;

	/**
	 * 缓存处理类
	 *
	 * @var UE_Cache_Abstract
	 */
	private $_storage = null;
	
	private static $_storages = null;

	/**
     * @return UE_Cache
     */
	static public function createCache($cacheDriver = '') {
		$cacheClass = 'UE_Cache_' . ucfirst(empty($cacheDriver) ? UE_Config::get('cache_driver') : $cacheDriver);
		return new self($cacheClass);
	}

	private function __construct($cacheClass) {
		if (isset(self::$_storages[$cacheClass])) {
			$this->_storage = self::$_storages[$cacheClass];
		} else {
		    $this->_storage = self::$_storages[$cacheClass] = new $cacheClass;
		}
	}

	/**
	 * 设置缓存
	 *
	 * @param string $key
	 * @param mixed $value
	 * @param int $expire
	 * @return UE_Cache
	 */
	public function set($key, $value, $expire = 0) {
		if (!$expire) {
			$expire = $this->_expire;
		}
		
		$this->_storage->checkLock($key);
		
		$data = array('time' => time(), 'expire' => $expire, 'valid' => true, 'data' => $value);
		$this->_storage->lock($key);
		
		try {
			$this->_storage->store($key, $data);
			$this->_storage->unlock($key);
		} catch (UE_Cache_Exception $e) {
			$this->_storage->unlock($key);
			throw $e;
		}

		return $this;
	}

	/**
	 * 读取缓存
	 *
	 * @param string $key
	 * @param bool $checkExpired 是否检查过期情况
	 * @return array|bool
	 */
	public function get($key, $checkExpired = true) {
		$data = $this->fetch($key);
		if ($data && (!$checkExpired || ($data['valid'] && !$data['isExpired']))) {
			return $data['data'];
		}
		
		return false;
	}

	/**
	 * 读缓存，包括过期的和无效的，取得完整的存贮结构
	 *
	 * @param string $key
	 * @return array|bool
	 */
	public function fetch($key)	{
		$this->_storage->checkLock($key);
		$data = $this->_storage->fetch($key);
		if ($data) {
			$data['isExpired'] = ($data['expire'] && (time() - $data['time']) > $data['expire']) ? true : false;
			return $data;
		}
		
		return false;
	}

	/**
	 * 删除缓存
	 *
	 * @param string $key
	 * @return UE_Cache
	 */
	public function delete($key) {
		$this->_storage->checkLock($key)
		               ->lock($key);

		try {
			$this->_storage->delete($key);
			$this->_storage->unlock($key);
		} catch (UE_Cache_Exception $e) {
			$this->_storage->unlock($key);
			throw $e;
		}

		return $this;
	}
	
	/**
	 * 清除缓存
	 * 
	 * @return UE_Cache
	 */
	public function clear($dir = '') {
		$this->_storage->clear($dir);
		return $this;
	}

	/**
	 * 把缓存设为无效
	 *
	 * @param string $key
	 * @return UE_Cache
	 */
	public function setInvalidate($key) {
		$this->_storage->checkLock($key)
		               ->lock($key);
		try {
			$data = $this->_storage->fetch($key);
			if ($data) {
				$data['valid'] = false;
				$this->_storage->store($key, $data);
			}
			$this->_storage->unlock($key);
		} catch (UE_Cache_Exception $e) {
			$this->_storage->unlock($key);
			throw $e;
		}

		return $this;
	}
	
	/**
	 * 设置缓存过期时间（s）
	 *
	 * @param int $expire
	 * @return UE_Cache
	 */
	public function setExpire($expire) {
		$this->_expire = (int) $expire;

		return $this;
	}
}

